package com.geline.sqlbackup.druid;

import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.DbType;
import com.geline.sqlbackup.bean.ColumnInfo;
import com.geline.sqlbackup.bean.SqlMapParam;
import com.geline.sqlbackup.bean.TableColumnInfo;
import com.geline.sqlbackup.enums.HtmlTypeEnum;
import com.geline.sqlbackup.util.JdbcDbTypeUtil;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 支持解析字段描述：@dict:{sys_xxx}; @table:{t_user}
 * 支持解析字段描述：@dict.{sys_xxx}; @table.{t_user}
 * @author mengx
 * @version 2020/12/27 21:12
 */
@Slf4j
public class DruidDdlHandlerUtils {

    /**
     * 解析DDL
     * @param dataSource
     * @param sqlMapParam
     * @return
     */
    public static TableColumnInfo parseTableColumnInfo(DataSource dataSource, SqlMapParam sqlMapParam) {
        DbType dbType = JdbcDbTypeUtil.getDbTypeOfDruid(dataSource);
        return parseTableColumnInfo(dbType, sqlMapParam);
    }

    /**
     * 解析DDL
     * @param dbType
     * @param sqlMapParam
     * @return
     */
    public static TableColumnInfo parseTableColumnInfo(DbType dbType, SqlMapParam sqlMapParam) {
        if(dbType == null || dbType==DbType.other){
            //不支持的数据库
            throw new RuntimeException("unsupported DB : "+dbType.name());
        }
        boolean useRemoveTableHead = sqlMapParam.getUseRemoveTableHead();
        boolean useCamelCase = sqlMapParam.getUseCamelCase();
        return parseTableColumnInfo(dbType, sqlMapParam.getDdlSql(), useRemoveTableHead, useCamelCase, null);
    }

    /**
     * 解析DDL
     * @param dataSource
     * @param ddlSql
     * @param useRemoveTableHead
     * @param useCamelCase
     * @return
     */
    public static TableColumnInfo parseTableColumnInfo(DataSource dataSource, String ddlSql, boolean useRemoveTableHead, boolean useCamelCase) {
        DbType dbType = JdbcDbTypeUtil.getDbTypeOfDruid(dataSource);
        return parseTableColumnInfo(dbType, ddlSql, useRemoveTableHead, useCamelCase);
    }

    public static TableColumnInfo parseTableColumnInfo(DbType dbType, String ddlSql, boolean useRemoveTableHead, boolean useCamelCase) {
        return parseTableColumnInfo(dbType, ddlSql, useRemoveTableHead, useCamelCase, null);
    }

    /**
     * 解析DDL
     * @param dbType
     * @param ddlSql
     * @param useRemoveTableHead
     * @param useCamelCase
     * @param ignoredColumns
     * @return
     */
    public static TableColumnInfo parseTableColumnInfo(DbType dbType, String ddlSql, boolean useRemoveTableHead, boolean useCamelCase, String ignoredColumns) {
        List<String> ignoredColumnList = new ArrayList<>();
        if(StrUtil.isNotBlank(ignoredColumns)){
            ignoredColumnList = Arrays.stream(ignoredColumns.split(",")).map(String::trim).collect(Collectors.toList());
        }
        TableColumnInfo tableColumnInfo = null;

        switch (dbType) {
            case oracle:
            case oceanbase_oracle: {
                tableColumnInfo = new OracleDdlSqlHandler().handler(ddlSql, ignoredColumnList, useRemoveTableHead, useCamelCase);
                break;
            }
            case sqlserver:{
                tableColumnInfo = new SqlServerDdlSqlHandler().handler(ddlSql, ignoredColumnList, useRemoveTableHead, useCamelCase);
                break;
            }
            case mysql:
            case mariadb:
            case drds: {
                tableColumnInfo = new MySqlDdlSqlHandler().handler(ddlSql, ignoredColumnList, useRemoveTableHead, useCamelCase);
                break;
            }
            default:{
                log.debug("current dbType = "+dbType.name());
                //tableColumnInfo = new MySqlDdlSqlHandler().handler(ddlSql, ignoredColumnList, useRemoveTableHead, useCamelCase);
                throw new RuntimeException("Un Supported DB : "+dbType);
            }
        }

        Set<String> findDictTypeSet = new HashSet<>();

        List<ColumnInfo> columnInfoList = tableColumnInfo.getColumnInfoList();
        columnInfoList.stream().forEach(columnInfo -> {
            String columnName = columnInfo.getColumnName();
            String dictType = null;
            String readTable = null;

            String columnComment = columnInfo.getColumnComment();
            if(StrUtil.isNotBlank(columnComment)){
                int dictIndex = columnComment.indexOf("@dict");
                if(dictIndex != -1){
                    //从字段注释里提取字典编码，如：@dict:sys_yes_no
                    if(columnComment.contains("@dict:") || columnComment.contains("@dict.")){
                        dictType = columnComment.substring(dictIndex+6).trim();
                    }else{
                        //注释标识了@dict，当前字段code即为字典类型code
                        dictType = columnName;
                    }
                    columnInfo.setColumnComment(columnComment.substring(0, dictIndex).trim());
                }

                //从字段注释里提取表编码，如：@table:t_user.id
                int tableIdx = columnComment.indexOf("@table:");
                if(tableIdx == -1){
                    tableIdx = columnComment.indexOf("@table.");
                }
                if(tableIdx != -1){
                    readTable = columnComment.substring(tableIdx+7).trim();
                    columnInfo.setColumnComment(columnComment.substring(0, tableIdx).trim());
                }
            }

            if(StrUtil.isNotBlank(readTable)){
                log.debug("find readTable = "+readTable);
                columnInfo.setReadTable(readTable);
            }
            if(StrUtil.isNotBlank(dictType)){
                columnInfo.setDictType(dictType);
                findDictTypeSet.add(dictType);
                columnInfo.setHtmlTypeEnum(HtmlTypeEnum.SELECT);
                //columnInfo.setOptions(propValueList);
            }
        });
        ArrayList<String> dictTypeLists = new ArrayList<>(findDictTypeSet);
        tableColumnInfo.setDictTypeList(dictTypeLists);
        return tableColumnInfo;
    }
}
